package com.lcy.struct.bTreePlus.disk.recovery.transation;

import com.lcy.struct.bTreePlus.disk.enums.BplusTreeEnums;
import com.lcy.struct.bTreePlus.disk.index.BTreeIndex;
import com.lcy.struct.bTreePlus.disk.item.TreeNode;
import com.lcy.struct.bTreePlus.disk.recovery.undo.UndoCenter;
import com.lcy.struct.bTreePlus.entity.TransactionJoinInfo;

import java.util.ArrayList;
import java.util.List;

/**
 * @author lucongyang
 * @date Created in  9:52
 * @description 事务中心，原子操作中心
 */
public class TransactionCenter {
    static ThreadLocal<Boolean> threadLocal = ThreadLocal.withInitial(() -> false);

    static ThreadLocal<Long> transactionLocal = new ThreadLocal<>();

    /**
     * 开启事务
     */
    public void startTransaction() {
        if (!threadLocal.get()) {
            threadLocal.set(true);
            transactionLocal.set(System.currentTimeMillis());
        }
    }

    /**
     * 事务的回滚
     */
    public void rollback() {
        if (threadLocal.get()) {
            List<String> transactionUndoStr = UndoCenter.getInstance().getTransactionUndoStr(getTransactionId());
            UndoCenter.getInstance().doUndo(getTransactionId(), transactionUndoStr);
            threadLocal.set(false);
        }
    }

    /**
     * 事务提交
     */
    public void commit() {
        if (threadLocal.get()) {
            UndoCenter.getInstance().commit(getTransactionId());
            threadLocal.set(false);
        }
    }

    public static TransactionCenter getInstance() {
        return TransactionCenterHandler.INSTANCE;
    }

    private static class TransactionCenterHandler {
        private static final TransactionCenter INSTANCE = new TransactionCenter();
    }

    private TransactionCenter() {
    }

    /**
     * 加入
     */
    public void join(List<TransactionJoinInfo> transactionJoinInfoList, BplusTreeEnums.TransactionType transactionType) {
        if (!threadLocal.get()) {
            return;
        }
        List<String> undoStrList = new ArrayList<>();
        for (TransactionJoinInfo transactionJoinInfo : transactionJoinInfoList) {
            String undoStr = null;
            switch (transactionType) {
                case ADD: {
                    undoStr = UndoCenter.getInstance().getAddUndo(transactionJoinInfo.getIndex());
                    break;
                }
                case UPDATE: {
                    undoStr = UndoCenter.getInstance().getUpdateUndo(transactionJoinInfo.getIndex(), transactionJoinInfo.getTreeNode());
                    break;
                }
                case DEL: {
                    undoStr = UndoCenter.getInstance().getDelUndo(transactionJoinInfo.getIndex());
                    break;
                }
                default: {
                }
            }
            if (undoStr != null) {
                undoStrList.add(undoStr);
            }
        }

        UndoCenter.getInstance().writeUndoStr(getTransactionId(), undoStrList);
    }

    /**
     * 事务id获取
     */
    private long getTransactionId() {
        return transactionLocal.get();
    }

    /**
     * 是否开启事务
     */
    public boolean isWithinTransaction() {
        return threadLocal.get();
    }
}
